import json, re

from django.shortcuts import render
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from django.http import JsonResponse
from oauth.models import OAuthQQUser
from django.contrib.auth import login
from meiduo_mall.utils.secret import SecretOauth
from django_redis import get_redis_connection
from users.models import User


class QQURLView(View):
    """提供QQ登录页面网址"""

    # (接口一)获取扫码登录页面url
    def get(self, request):
        # next_page 表示从哪个页面进入到的登录页面，将来登录成功后，就自动回到那个页面
        next_page = request.GET.get("next")

        # 获取 QQ 登录页面网址，创建 OAuthQQ 类的对象
        oauth = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,            # 文档中的appid即应用id
            client_secret=settings.QQ_CLIENT_SECRET,    # 文档中的appkey即应用密钥
            redirect_uri=settings.QQ_REDIRECT_URI,      # QQ身份验证之后用户跳转回美多的页面链接
            state=next_page,                            # 整个登陆流程结束，浏览器跳转回的页面
        )

        # 调用对象的获取 qq 地址方法
        login_url = oauth.get_qq_url()

        # 返回登录地址
        return JsonResponse({
            'code': 0,
            'errmsg': 'OK',
            'login_url': login_url
        })


class QQUserView(View):
    """用户扫码登录的回调处理"""

    # (接口二)获取openid
    def get(self, request):
        # ==============获取openid===============
        # 获取前端发送过来的 code 参数:
        code = request.GET.get("code")
        # print(code)
        if code is None:
            return JsonResponse({"code": 400, "errmsg": "缺少code参数"})

        # 1.创建工具对象
        oauth = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            client_secret=settings.QQ_CLIENT_SECRET,
            redirect_uri=settings.QQ_REDIRECT_URI,
            state=None,
        )
        try:
            # 2.携带 code 向 QQ服务器 请求 access_token
            access_token = oauth.get_access_token(code)
            # 3.携带 access_token 向 QQ服务器 请求 openid
            openid = oauth.get_open_id(access_token)
            # print(access_token, openid)
        except Exception as e:
            # 如果上面获取 openid 出错, 则验证失败，返回结果
            return JsonResponse({'code': 400, 'errmsg': 'oauth2.0认证失败, 获取qq信息失败'})

        # ==============判断用户是否绑定===============
        # TODO: 获取openid说明用户qq身份验证成功，接下来补充后续判断用户是否绑定逻辑代码。
        try:
            oauth_qq = OAuthQQUser.objects.get(openid=openid)
        except Exception as e:
            # 如果 openid 没绑定美多商城用户 —— 加密openid返回，用于后续绑定接口
            # 使用加密类加密 openid
            access_token = SecretOauth().dumps({"openid": openid})
            # 注意: 这里一定不能返回0的状态码. 否则不能进行绑定页面
            return JsonResponse({'code': 400, 'errmsg': '未绑定', 'access_token': access_token})
        else:
            # 如果 openid 已绑定美多商城用户
            user = oauth_qq.user
            login(request, user)  # 状态保持
            response = JsonResponse({'code': 0, 'errmsg': 'QQ登陆成功'})  # 构建响应
            response.set_cookie("username", user.username, max_age=3600 * 24 * 14)  # 设置cookie
            return response

    # (接口三)绑定用户
    def post(self, request):
        # 1、提取参数
        data_dict = json.loads(request.body.decode("utf-8"))
        mobile = data_dict.get("mobile")
        password = data_dict.get("password")
        sms_code_client = data_dict.get("sms_code")
        # 密文openid字符串
        access_token = data_dict.get("access_token")

        # 2、校验参数
        # 2.1、必要性校验
        if not all([mobile, password, sms_code_client]):
            return JsonResponse({'code': 400, 'errmsg': '缺少必传参数'})
        # 2.2、约束条件校验
        # 手机号
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': 400, 'errmsg': '请输入正确的手机号码'})
        # 密码
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return JsonResponse({'code': 400, 'errmsg': '请输入8-20位的密码'})

        # 2.3、业务性校验
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        if sms_code_server is None:
            # 短信验证码过期
            return JsonResponse({'code': 400, 'errmsg': '验证码失效'})
        if sms_code_client != sms_code_server.decode("utf-8"):
            # 用户输入不匹配
            return JsonResponse({'code': 400, 'errmsg': '输入的验证码有误'})

        # 4、业务数据处理
        # 4.1、解密token值，获取openid
        content_dict = SecretOauth().loads(access_token)
        if content_dict is None:
            return JsonResponse({'code': 400, 'errmsg': '无效token'})
        openid = content_dict.get("openid")
        # 4.2、获取用户对象
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 用户不存在,新建用户(好不容易来了个用户，一定不要放过，一定要让他注册美多商城账号！)
            user = User.objects.create_user(
                username=mobile,  # 用户绑定页面未要求输入用户名，此处我们默认把用户手机号作用户名
                password=password,
                mobile=mobile,
            )
        else:
            # 如果用户存在，检查用户密码
            if not user.check_password(password):
                return JsonResponse({'code': 400, 'errmsg': '输入的密码不正确'})
        # 4.3、将用户绑定 openid
        try:
            OAuthQQUser.objects.create(
                openid=openid,
                user=user,
            )
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '往数据库添加数据出错'})
        # 4.4、状态保持
        login(request, user)
        # 4.5、构建响应
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie("username", user.username, max_age=3600 * 24 * 14)  # 设置cookie

        # TODO：登陆成功后合并购物车
        from carts.utils import merge_cart_cookie_to_redis
        merge_cart_cookie_to_redis(request=request, response=response)

        return response

